<?php
/**
 * Created by PhpStorm.
 * User: Mo
 * Date: 15-6-10
 * Time: 上午11:07
 */

/************************************************
 ** print_a class and helper function
 ** prints out an array in a more readable way
 ** than print_r()
 **
 ** based on the print_a() function from
 ** Stephan Pirson (Saibot)
 ************************************************/
class Print_a_class
{

    # this can be changed to true if you want
    var $look_for_leading_tabs = false;

    var $output;
    var $iterations;
    var $key_bg_color   = '1E32C8';
    var $value_bg_color = 'DDDDEE';
    var $fontsize       = '8pt';
    var $keyalign       = 'left';
    var $fontfamily     = 'Verdana';
    var $show_object_vars;
    var $limit;

    // function Print_a_class() {}

    # recursive function!

    /* this internal function looks if the given array has only numeric values as  */
    function _only_numeric_keys($array)
    {
        $test = true;
        if (is_array($array)) {
            foreach (array_keys($array) as $key) {
                if (!is_numeric($key)) {
                    $test = false;
                } /* #TODO# */
            }

            return $test;
        } else {
            return false;
        }
    }

    function _handle_whitespace($string)
    {
        $string = str_replace(' ', '&nbsp;', $string);
        $string = preg_replace(array('/&nbsp;$/', '/^&nbsp;/'), '<span style="color:red;">_</span>',
            $string); /* replace spaces at the start/end of the STRING with red underscores */
        $string = preg_replace('/\t/', '&nbsp;&nbsp;<span style="border-bottom:#' . $this->value_bg_color . ' solid 1px;">&nbsp;</span>',
            $string); /* replace tabulators with '_ _' */

        return $string;
    }

    function print_a($array, $iteration = false, $key_bg_color = false)
    {
        $key_bg_color or $key_bg_color = $this->key_bg_color;

        # lighten up the background color for the key td's =)
        if ($iteration) {
            for ($i = 0; $i < 6; $i += 2) {
                $c = substr($key_bg_color, $i, 2);
                $c = hexdec($c);
                ($c += 15) > 255 and $c = 255;
                isset($tmp_key_bg_color) or $tmp_key_bg_color = '';
                $tmp_key_bg_color .= sprintf("%02X", $c);
            }
            $key_bg_color = $tmp_key_bg_color;
        }

        # build a single table ... may be nested
        $this->output .= '<table style="border:none;" cellspacing="1">';
        $only_numeric_keys = ($this->_only_numeric_keys($array) || count($array) > 50);
        $i = 0;
        foreach ($array as $key => $value) {
            if ($only_numeric_keys && $this->limit && $this->limit == $i++) {
                break;
            } /* if print_a() was called with a fourth parameter #TODO# */

            $value_style_box = 'color:black;';
            $key_style = 'color:white;';

            $type = gettype($value);
            # print $type.'<br />';

            # change the color and format of the value and set the values title
            $type_title = $type;
            $value_style_content = '';
            switch ($type) {
                case 'array':
                    if (empty($value)) {
                        $type_title = 'empty array';
                    }
                    break;

                case 'object':
                    $key_style = 'color:#FF9B2F;';
                    break;

                case 'integer':
                    $value_style_box = 'color:green;';
                    break;

                case 'double':
                    $value_style_box = 'color:blue;';
                    break;

                case 'boolean':
                    if ($value == true) {
                        $value_style_box = 'color:#D90081;';
                    } else {
                        $value_style_box = 'color:#84009F;';
                    }
                    break;

                case 'NULL':
                    $value_style_box = 'color:darkorange;';
                    break;

                case 'string':
                    if ($value == '') {

                        $value_style_box = 'color:darkorange;';
                        $value = "''";
                        $type_title = 'empty string';

                    } else {

                        $value_style_box = 'color:black;';
                        $value = htmlspecialchars($value);
                        if ($this->look_for_leading_tabs && _check_for_leading_tabs($value)) {
                            $value = _remove_exessive_leading_tabs($value);
                        }
                        $value = $this->_handle_whitespace($value);
                        $value = nl2br($value);

                        /* use different color for string background */
                        if (strstr($value, "\n")) {
                            $value_style_content = 'background:#ECEDFE;';
                        }

                    }
                    break;
            }

            $this->output .= '<tr>';
            $this->output .= '<td nowrap="nowrap" align="' . $this->keyalign . '" style="padding:0px 3px 0px 3px;background-color:#' . $key_bg_color . ';' . $key_style . ';font:bold ' . $this->fontsize . ' ' . $this->fontfamily . ';" title="' . gettype($key) . '[' . $type_title . ']">';
            $this->output .= $this->_handle_whitespace($key);
            $this->output .= '</td>';
            $this->output .= '<td nowrap="nowrap" style="background-color:#' . $this->value_bg_color . ';font: ' . $this->fontsize . ' ' . $this->fontfamily . '; color:black;">';

            # value output
            if ($type == 'array' && preg_match('/#RAS/', $key)) { /* only used for special recursive array constructs which i use sometimes */
                $this->output .= '<div style="' . $value_style_box . '">recursion!</div>';
            } elseif ($type == 'array') {
                if (!empty($value)) {
                    $this->print_a($value, true, $key_bg_color);
                } else {
                    $this->output .= '<span style="color:darkorange;">[]</span>';
                }
            } elseif ($type == 'object') {
                if ($this->show_object_vars) {
                    $objects_class = get_class($value);
                    $this->print_a(array('CLASS_NAME' => $objects_class), true, '204FB8');
                    $this->print_a(array('CLASS_VARS' => get_class_vars($objects_class)), true, '2066B8');
                    $this->print_a(array('CLASS_METHODS' => get_class_methods($objects_class)), true, '2067EB8');
                    $this->print_a(array('OBJECT_VARS' => get_object_vars($value)), true, '2095B8');
                } else {
                    $this->output .= '<div style="' . $value_style_box . '">OBJECT</div>';
                }
            } elseif ($type == 'boolean') {
                $this->output .= '<div style="' . $value_style_box . '" title="' . $type . '">' . ($value ? 'true' : 'false') . '</div>';
            } elseif ($type == 'NULL') {
                $this->output .= '<div style="' . $value_style_box . '" title="' . $type . '">NULL</div>';
            } else {
                $this->output .= '<div style="' . $value_style_box . '" title="' . $type . '"><span style="' . $value_style_content . '">' . $value . '</span></div>';
            }

            $this->output .= '</td>';
            $this->output .= '</tr>';
        }

        $entry_count = count($array);
        $skipped_count = $entry_count - $this->limit;

        if ($only_numeric_keys && $this->limit && count($array) > $this->limit) {
            $this->output .= '<tr title="showing ' . $this->limit . ' of ' . $entry_count . ' entries in this array"><td style="text-align:right;color:darkgray;background-color:#' . $key_bg_color . ';font:bold ' . $this->fontsize . ' ' . $this->fontfamily . ';">...</td><td style="background-color:#' . $this->value_bg_color . ';font:' . $this->fontsize . ' ' . $this->fontfamily . ';color:darkgray;">[' . $skipped_count . ' skipped]</td></tr>';
        }
        $this->output .= '</table>';
    }
}